/*********************************************************************************
 *      Copyright:  (C) 2022 Zhang Changxing<ZhangChangxingVIP@163.com>
 *                  All rights reserved.
 *
 *       Filename:  sms_pdu.c
 *    Description:  This file function mainly packs the PDU encoding of center number, source number and SMS.
 *                 
 *        Version:  1.0.0(07/28/2022)
 *         Author:  Zhang Changxing <ZhangChangxingVIP@163.com>
 *      ChangeLog:  1, Release initial version on "07/28/2022  01:33:25 AM"
 *                 
 ********************************************************************************/



#include "sms_pdu.h"


/*-------------------------------------------------------------------------
 *   description:   Get and process the center number
 *          args:   $center_buf:    Receive the processed center number
 *  return value:   <0: failure,    =0:ok 
 *-------------------------------------------------------------------------*/
int processing_center_number(char *center_buf)
{
    char    temp_buf[256] = {0};
    int     i = 0;
    int     temp =0;

    if (!center_buf)
    {
        log_error("[%s]The argument invalid!\n", __func__);
        return -1;
    }

    strcpy(center_buf, &center_buf[1]);
    strcat(center_buf, "F");

    for (i = 0; i < strlen(center_buf); i += 2)
    {
        temp = center_buf[i];
        center_buf[i] = center_buf[i+1];
        center_buf[i+1] = temp;
    }

    snprintf(temp_buf, strlen(center_buf)+strlen("0891")+1, "0891%s", center_buf);
    memset(center_buf, 0 , sizeof(center_buf));
    strncpy(center_buf, temp_buf, strlen(temp_buf));

    log_debug("[%s]Processing center number succeeded:%s\n", __func__, center_buf);

    return 0;
}


/*-------------------------------------------------------------------------
 *   description:   Get and process the target number
 *          args:   $center_buf:    Receive the processed center number
 *  return value:   <0: failure,    =0:ok 
 *-------------------------------------------------------------------------*/
int processing_phone_number(char *phone_buf)
{
    char    temp_buf[256] = {0};
    int     i = 0;
    int     temp =0;

    if (!phone_buf)
    {
        log_error("[%s]The argument invalid!\n", __func__);
        return -1;
    }

    strcpy(phone_buf, &phone_buf[1]);
    strcat(phone_buf, "F");

    for (i = 0; i < strlen(phone_buf); i += 2)
    {
        temp = phone_buf[i];
        phone_buf[i] = phone_buf[i+1];
        phone_buf[i+1] = temp;
    }

    sprintf(temp_buf, "11000D91%s000800", phone_buf);
    memset(phone_buf, 0, sizeof(phone_buf));
    strncpy(phone_buf, temp_buf, strlen(temp_buf));

    log_info("[%s]Phone_number processing succeeded:%s\n", __func__, phone_buf);

    return 0;
}


/*-------------------------------------------------------------------------
 *   description:   Convert UTF8 encoding format to Unicode encoding format
 *          args:   $utf8_buf:      UTF8 Encoding format string
 *                  $unicode_buf    Stores the address of the Unicde coding buffer
 *                  $len            Unicde Indicates the encoded byte length
 *  return value:   <0: failure,    =0:ok 
 *-------------------------------------------------------------------------*/
int utf8_to_unicode(char *utf8_buf, char *unicode_buf, int *len)
{
    char    Byte1, Byte2, Byte3, Byte4;
    char    *ptr = unicode_buf;
    int     i = 0;
    *ptr    = 0;

    if (!utf8_buf)
    {
        log_error("[%s]The argument invalid!\n", __func__);
        return -1;
    }
    
    while (*utf8_buf)
    {
        if ((*utf8_buf & 0x80) == 0x00)
        {
            ptr++;
            *ptr = *utf8_buf;
            ptr++;
            utf8_buf++;
            i +=2;
        }
        else if ((*utf8_buf & 0xE0) == 0xC0)
        {
            Byte1 = *utf8_buf;
            Byte2 = *(utf8_buf + 1);

            if ((Byte2 & 0xC0) != 0x80)
                return -2;
            
            *ptr = ((Byte1 >> 2) & 0x07);
            ptr++;
            *ptr = (Byte1 << 6) + (Byte2 & 0x3F);
            ptr++;
            utf8_buf +=2;
            i +=2;
        }
        else if ((*utf8_buf & 0xF0) == 0xE0)
        {
            Byte1 = *utf8_buf;
            Byte2 = *(utf8_buf + 1);
            Byte3 = *(utf8_buf + 2);

            *ptr = (Byte1 << 4) + ((Byte2 >> 2) & 0x0F);
            ptr++;
            *ptr = (Byte2 << 6) + (Byte3 & 0x3F);
            ptr++;
            utf8_buf += 3;
            i += 2;
        }
        else if ((*utf8_buf & 0xF8) == 0xF0)
        {
            Byte1 = *utf8_buf;
            Byte2 = *(utf8_buf + 1);
            Byte3 = *(utf8_buf + 2);
            Byte4 = *(utf8_buf + 3);

            *ptr = ((Byte1 & 0x07) << 2) + ((Byte2 >> 4) & 0x03);
            ptr++;
            *ptr = (Byte2 << 4) + ((Byte3 >> 2) & 0x0F);
            ptr++;
            *ptr = (Byte2 <<6) + (Byte4 & 0x3F);
            utf8_buf +=3;
            i += 4;
        }
    }

    *len = i;

    //log_debug("strlen(unicode_buf):%d\n", strlen(unicode_buf));

    return 0;
}


/*-------------------------------------------------------------------------
 *   description:   Byte stream character stream
 *          args:   $src_buf:       Byte stream buffer address
 *                  $dest_buf:      Character stream buffer address
 *                  $source_len:    Byte stream buffer length
 *  return value:   <0: failure,    =0:ok 
 *-------------------------------------------------------------------------*/
int hex_to_str(char *dest_buf, char *src_buf, int src_len)
{
    int i = 0;
    char *ptr = dest_buf;

    for (i; i< src_len; i++)
    {
        log_debug("src_buf[%d]:%02x\n", i, src_buf[i]);
        sprintf(ptr, "%02x",src_buf[i]);
        ptr += 2;
    }

    return 0;
}



/*-------------------------------------------------------------------------
 *   description:   The center number, destination number, and short message 
 *                  are packaged into a PDU package
 *          args:   $center_buf:    Address of the center number buffer that 
 *                  has been processed
 *                  $phone_buf:     Target number buffer address already processed
 *                  $sms_buf:       Address of the processed SMS buffer
 *                  $pdu_buf:       Address of the packed PDU buffer
 *                  $cmgs_length    The sum of the length of the target number 
 *                  and the data section
 *  return value:   <0: failure,    =0:ok 
 *------------------------------------------------------------------------*/
int pdu_packet(char *center_buf, char *phone_buf, char *sms_buf, char *pdu_buf, int *cmgs_length)
{
    char    temp[512] = {0};
    char    dest_buf[512] = {0};
    char    unicode_buf[512] = {0};
    int     unicode_len = 0;

    if (!center_buf || !phone_buf || !sms_buf)
    {
        log_error("[%s]The argument invalid!\n", __func__);
        return -1;
    }

    processing_center_number(center_buf);
    printf("[%s]center number:%s\n", __func__, center_buf);

    //printf("[%s]phone_buf:%s\n", __func__, phone_buf);
    processing_phone_number(phone_buf);
    printf("[%s]phone number:%s\n", __func__, phone_buf);


    printf("[%s]sms_buf:%s\n", __func__, sms_buf);
    utf8_to_unicode(sms_buf, unicode_buf, &unicode_len);

    hex_to_str(dest_buf, unicode_buf, unicode_len);
    printf("[%s]SMS PDU:%s\n", __func__, dest_buf);

    sprintf(temp, "%s%02x%s", phone_buf, strlen(dest_buf)/2, dest_buf);
    *cmgs_length  = strlen(temp)/2;

    strncat(pdu_buf, center_buf, strlen(center_buf));
    strncat(pdu_buf, temp, strlen(temp));
    

    log_info("[%s]cmgs_length:%d\n pdu_buf:%s\n", __func__, *cmgs_length, pdu_buf);

    return 0;
}
